Obafemi Emmanuel

Navigation & Routing in Flutter

Published 3 months ago

Flutter provides a powerful and flexible navigation system, allowing developers to manage app screens efficiently. In this blog, we will explore different aspects of navigation in Flutter, including Named vs Anonymous Routing, Passing Data Between Screens, Navigation using GoRouter, and Deep Linking in Flutter.


1ļøāƒ£ Named vs Anonymous Routing

Flutter provides two primary methods for routing: Named Routing and Anonymous Routing.


šŸ”¹ Anonymous Routing (Direct Navigation)

Anonymous routing, also known as push-based navigation, uses the Navigator.push method to navigate between screens without assigning names to routes.


Example:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: HomeScreen()));
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondScreen()),
            );
          },
          child: Text('Go to Second Screen'),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(child: Text('Welcome to Second Screen!')),
    );
  }
}

šŸ”¹ Named Routing

Named routing assigns a name to each route and allows navigation using these names, which is useful in large applications.


Example:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    initialRoute: '/',
    routes: {
      '/': (context) => HomeScreen(),
      '/second': (context) => SecondScreen(),
    },
  ));
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/second');
          },
          child: Text('Go to Second Screen'),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(child: Text('Welcome to Second Screen!')),
    );
  }
}

Which One to Use?

  • Anonymous Routing is suitable for small apps or when navigation is dynamic.
  • Named Routing is preferred for large apps where maintaining navigation centrally is beneficial.

2ļøāƒ£ Passing Data Between Screens

šŸ”¹ Passing Data using Constructor

class SecondScreen extends StatelessWidget {
  final String message;
  SecondScreen({required this.message});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(child: Text(message)),
    );
  }
}

// Passing data during navigation
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondScreen(message: 'Hello Flutter!')),
);

šŸ”¹ Passing Data with Named Routes

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final String message = ModalRoute.of(context)!.settings.arguments as String;
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(child: Text(message)),
    );
  }
}

// Navigating with arguments
Navigator.pushNamed(
  context,
  '/second',
  arguments: 'Hello from Home Screen!',
);

3ļøāƒ£ Navigation using GoRouter

GoRouter is a powerful package for declarative routing in Flutter.


šŸ”¹ Installing GoRouter

Add the dependency:

dependencies:
  go_router: ^12.1.1

šŸ”¹ Setting Up GoRouter

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() {
  runApp(MyApp());
}

final GoRouter _router = GoRouter(
  routes: [
    GoRoute(path: '/', builder: (context, state) => HomeScreen()),
    GoRoute(path: '/second', builder: (context, state) => SecondScreen()),
  ],
);

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
    );
  }
}

šŸ”¹ Navigating using GoRouter

GoRouter.of(context).go('/second');

4ļøāƒ£ Deep Linking in Flutter

Deep linking allows users to open a specific screen in the app using a URL.


šŸ”¹ Setting Up Deep Linking

  1. Add a custom URL scheme in AndroidManifest.xml:
<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <data android:scheme="myapp" android:host="example.com" />
</intent-filter>
  1. Handle deep links in Flutter using onGenerateRoute:
onGenerateRoute: (settings) {
  if (settings.name == '/second') {
    return MaterialPageRoute(builder: (context) => SecondScreen());
  }
  return null;
},
  1. Using Firebase Dynamic Links for deep linking:
  • Configure Firebase Dynamic Links in the Firebase Console.
  • Use firebase_dynamic_links package to handle the links inside the app.
FirebaseDynamicLinks.instance.onLink.listen((dynamicLinkData) {
  Navigator.pushNamed(context, dynamicLinkData.link.path);
});

Conclusion

Flutter provides multiple ways to handle navigation, each suited for different app architectures. Whether you prefer Named or Anonymous Routing, need to pass data between screens, use the powerful GoRouter, or implement Deep Linking, Flutter has the tools you need to build seamless user experiences.

By mastering these navigation techniques, you can build well-structured and scalable Flutter applications!


Leave a Comment


Choose Colour